#include <stdio.h>     // 提供输入输出函数，如 printf、scanf、fgets
#include <stdlib.h>    // 提供 malloc、free 函数
#include <string.h>    // 提供字符串函数，如 strlen、strcmp、strncpy、fgets

#define MAX_LEN 1000   // 定义最大字符串长度

// step 1# 主函数入口
int main() {
    char s1[MAX_LEN], s2[MAX_LEN];

    // step 2# 读取两行字符串
    fgets(s1, sizeof(s1), stdin);          // 读取第一行字符串
    fgets(s2, sizeof(s2), stdin);          // 读取第二行字符串

    // 去除换行符（如果存在）
    s1[strcspn(s1, "\n")] = '\0';
    s2[strcspn(s2, "\n")] = '\0';

    int n = strlen(s1);                    // s1 的长度
    int m = strlen(s2);                    // s2 的长度

    // step 3# 创建二维 dp 数组，dp[i][j] 表示 s1前i个、s2前j个字符末尾相同的子串长度
    int** dp = (int**)malloc((n + 1) * sizeof(int*));  // 动态分配行
    for (int i = 0; i <= n; i++) {
        dp[i] = (int*)calloc(m + 1, sizeof(int));       // 每行初始化为0
    }

    int maxLen = 0;                       // 最长公共子串长度
    int endIndex = 0;                     // s1中最长公共子串的结尾索引（用于截取）

    // step 4# 填充 dp 表，寻找最长公共子串
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            if (s1[i - 1] == s2[j - 1]) {            // 当前字符相等
                dp[i][j] = dp[i - 1][j - 1] + 1;     // 子串长度加1

                if (dp[i][j] > maxLen) {
                    maxLen = dp[i][j];               // 更新最大长度
                    endIndex = i;                    // 记录s1中子串结尾位置
                }
            } else {
                dp[i][j] = 0;                        // 不相等则无公共子串
            }
        }
    }

    // step 5# 输出最长公共子串
    for (int i = endIndex - maxLen; i < endIndex; i++) {
        putchar(s1[i]);   // 按字符输出最长公共子串
    }

    // step 6# 释放动态内存
    for (int i = 0; i <= n; i++) {
        free(dp[i]);
    }
    free(dp);

    return 0;
}
